<?php
/**
 * Description: 获取支付宝app支付需要的参数
 * User: devforma
 * Date: 15/11/17
 * Time: 19:44
 */

require CONFIG_DIR . '/pay.config.php';
require PUBLIC_DIR . '/payment/includes/WeixinPay.class.php';

class GetWxpayParams implements iController {
    private $appId = '';
    private $appSecret = '';
    private $partnerId = '';
    private $partnerKey = '';
    private $notifyUrlParam = '';
    private $appType = '';
    private $openid = '';

    /**
     * 微信支付对象
     * @var WeixinPay object
     */
    private $_wxPay = null;

    /**
     * api请求处理主函数
     * @param array $queryArgs 就是$_REQUEST变量
     * @return array api返回结果，必须含response_code
     */
    public function output($queryArgs) {

        if (validateUser($queryArgs) !== 1 || !isset($queryArgs['order_id'])
            || !filter_var($queryArgs['order_id'], FILTER_VALIDATE_INT)) {
            return genOutput(1000);
        }

        if (empty($queryArgs['app_type']) || !in_array($queryArgs['app_type'], array('dailylearn', 'quizbank', 'dailyplan', 'gongzhonghao', 'native'), true)) {
            return genOutput(1000);
        }

        if (empty($_SERVER['REMOTE_ADDR']))
            return genOutput(1000);

        $this->_wxPay = new WeixinPay();

        $this->appType = empty($queryArgs['app_type']) ? '' : $queryArgs['app_type'];
        $this->openid = empty($queryArgs['openid']) ? '' : $queryArgs['openid'];

        $this->initAppSetting($this->appType);
        if ($this->appId === '')
            return genOutput(1000);

        if (($orderInfo = $this->getOrderInfo($queryArgs['order_id'], $queryArgs['user_id']))
            && ($params = $this->genParams($orderInfo))) {

            return genOutput(1, $params);
        }

        return genOutput(1001);
    }

    private function initAppSetting($appType) {
        switch ($appType) {
            case 'dailyplan':
                $this->appId = WXPAY_DAILYPLAN_APP_ID;
                $this->appSecret = WXPAY_DAILYPLAN_APP_SECRET;
                $this->partnerId = WXPAY_DAILYPLAN_PARTNER_ID;
                $this->partnerKey = WXPAY_DAILYPLAN_PARTNER_KEY;
                $this->notifyUrlParam = 'dailyplan';
                break;

            case 'dailylearn':
                $this->appId = WXPAY_DAILYLEARN_APP_ID;
                $this->appSecret = WXPAY_DAILYLEARN_APP_SECRET;
                $this->partnerId = WXPAY_DAILYLEARN_PARTNER_ID;
                $this->partnerKey = WXPAY_DAILYLEARN_PARTNER_KEY;
                $this->notifyUrlParam = 'dailylearn';
                break;

            case 'quizbank':
                $this->appId = WXPAY_QUIZBANK_APP_ID;
                $this->appSecret = WXPAY_QUIZBANK_APP_SECRET;
                $this->partnerId = WXPAY_QUIZBANK_PARTNER_ID;
                $this->partnerKey = WXPAY_QUIZBANK_PARTNER_KEY;
                $this->notifyUrlParam = 'quizbank';
                break;

            case 'gongzhonghao':
            case 'native':
                $this->appId = WXPAY_HAO_APP_ID;
                $this->appSecret = WXPAY_HAO_APP_SECRET;
                $this->partnerId = WXPAY_HAO_PARTNER_ID;
                $this->partnerKey = WXPAY_HAO_PARTNER_KEY;
                $this->notifyUrlParam = 'gongzhonghao';
                break;

            default:
               break;
        }
    }

    /**
     * 生成app支付参数
     *
     * @param $orderInfo
     * @return bool|array
     */
    private function genParams($orderInfo) {
        if ($this->appType == 'native' && ($codeUrl = $this->getPrepayCodeUrl($orderInfo))) {
            return array('code_url' => $codeUrl);

        } elseif ($this->appType != 'native' && ($prepayId = $this->getPrepayId($orderInfo))) {
            if ($this->appType === 'gongzhonghao') { //公众号支付
                $params = array(
                    'appId' => $this->appId,
                    'package' => 'prepay_id='.$prepayId,
                    'nonceStr' => self::genNoncestr($orderInfo->order_id),
                    'timeStamp' => (string)time(),
                    'signType' => 'MD5'
                );

                $params['paySign'] = $this->_wxPay->sign($params, $this->partnerKey);

            } else { //App支付
                $params = array(
                    'appid' => $this->appId,
                    'partnerid' => $this->partnerId,
                    'prepayid' => $prepayId,
                    'package' => 'Sign=WXPay',
                    'noncestr' => self::genNoncestr($orderInfo->order_id),
                    'timestamp' => time(),
                );

                $params['sign'] = $this->_wxPay->sign($params, $this->partnerKey);

                $params['package_value'] = $params['package'];
                unset($params['package']);
            }

            return $params;
        }

        return false;
    }

    /**
     * 生成nonce字符串
     *
     * @param $uniqId
     * @return string
     */
    private static function genNoncestr($uniqId) {
        return md5($uniqId . time());
    }

    /**
     * 获取预支付交易码
     *
     * @param $orderInfo
     * @return bool|string
     */
    private function getPrepayId($orderInfo) {

        $info = $this->getProductInfo($orderInfo->product_id, $orderInfo->product_type);
        $params = array(
            'appid' => $this->appId,
            'mch_id' => $this->partnerId,
            'nonce_str' => self::genNoncestr($orderInfo->order_id),
            'body' => $info['name'],
            'out_trade_no' => $orderInfo->order_id,
            'total_fee' => $orderInfo->price * 100,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
            'notify_url' => WX_MOBILE_NOTIFY_URL,
            'attach' => $this->notifyUrlParam,
            'time_expire' => date('YmdHis', time() + $info['valid_pay_period']*60), //过期时间
            'trade_type' => $this->appType == 'gongzhonghao' ? 'JSAPI' : 'APP'
        );

        //公众号支付需要用户openid
        if ($this->appType === 'gongzhonghao') {
            $params['device_info'] = 'WEB';
            $params['openid'] = $this->openid;
        }

        $params['sign'] = $this->_wxPay->sign($params, $this->partnerKey);

        $result = httpPost(WeixinPay::getPrepayUrl(), $this->_wxPay->array2xml($params));
        $result = $this->_wxPay->xml2array($result);
        if (!empty($result) && $this->_wxPay->verifyReturn($result, $this->partnerKey)) {
            if (isset($result['prepay_id']))
                return $result['prepay_id'];
        }

        return false;
    }

    /**
     * 获取预支付交易码(扫码支付)
     *
     * @param $orderInfo
     * @return bool|string
     */
    private function getPrepayCodeUrl($orderInfo) {

        $info = $this->getProductInfo($orderInfo->product_id, $orderInfo->product_type);
        $params = array(
            'appid' => $this->appId,
            'mch_id' => $this->partnerId,
            'nonce_str' => self::genNoncestr($orderInfo->order_id),
            'body' => $info['name'],
            'out_trade_no' => $orderInfo->order_id,
            'total_fee' => $orderInfo->price * 100,
            'spbill_create_ip' => '120.55.245.247', //负载均衡地址
            'notify_url' => WX_MOBILE_NOTIFY_URL,
            'attach' => $this->notifyUrlParam,
            'time_expire' => date('YmdHis', time() + $info['valid_pay_period']*60), //过期时间
            'trade_type' => 'NATIVE',
            'product_id' => $orderInfo->product_id
        );

        $params['sign'] = $this->_wxPay->sign($params, $this->partnerKey);

        $result = httpPost(WeixinPay::getPrepayUrl(), $this->_wxPay->array2xml($params));
        $result = $this->_wxPay->xml2array($result);
        if (!empty($result) && $this->_wxPay->verifyReturn($result, $this->partnerKey)) {
            if (isset($result['code_url']))
                return $result['code_url'];
        }

        return false;
    }

    /**
     * 获取商品信息
     *
     * @param $productId
     * @param $productType
     * @return array
     */
    private function getProductInfo($productId, $productType) {
        global $cmsdb;

        $info = array('name' => '', 'valid_pay_period' => 30);

        switch ($productType) {
            case 'zhiboke':
                $data = getOrderCourseInfo($productId);

                $info['name'] = $data->course_name;
                if ($data->valid_pay_period)
                    $info['valid_pay_period'] = $data->valid_pay_period;

                break;

            case 'course':
                $sql = 'SELECT `course_name` FROM `data_vod_course` WHERE `id`=:id';
                $info['name'] = $cmsdb->getVar($sql, array(':id' => $productId));

                break;

            case 'interview':
                $sql = 'SELECT `product_name` FROM `conf_product` WHERE `id`=:id';
                $info['name'] = $cmsdb->getVar($sql, array(':id' => $productId));

                break;

            default:
                break;
        }

        $info['name'] = str_replace('+', '和', $info['name']);

        return $info;
    }

    /**
     * 获取订单信息,并更新app类型
     *
     * @param $orderId
     * @param $userId
     * @return mixed
     */
    private function getOrderInfo($orderId, $userId) {
        global $cmsdb;

        $exists = getOrderInfo($orderId, $userId);

        if ($exists) {
            $cmsdb->update('original_orders', array('app_type' => $this->appType), array('order_id' => $orderId));
            return $exists;
        }

        return false;
    }
}
